package public

import (
	"server/game/cache"
	"server/game/itypes"
	"server/game/model"
	"server/share/config"
	"strconv"
	"strings"

	"github.com/hwcer/cosgo"
	"github.com/hwcer/cosgo/random"
	"github.com/hwcer/cosgo/slice"
	"github.com/hwcer/cosgo/utils"
	"github.com/hwcer/logger"
	"github.com/hwcer/updater"
	"github.com/hwcer/yyds/context"
	"github.com/hwcer/yyds/errors"
	"github.com/hwcer/yyds/players/emitter"
	"github.com/hwcer/yyds/players/player"
)

func init() {
	cosgo.On(cosgo.EventTypLoaded, func() error {
		emitter.Events.On(config.Data.Events.TaskSubmit, Egg.onTaskSubmit)
		return nil
	})
}
func (this *egg) onTaskSubmit(u *updater.Updater, vs ...int32) {
	if len(vs) == 0 {
		return
	}
	id := vs[0]
	taskConfig := config.Data.Task[id]
	if taskConfig == nil || taskConfig.Tag != config.Data.TaskTag.EggTask {
		return
	}
	daily := u.Document(config.ITypeDaily)
	var data map[int32]int32
	if i := daily.Get("eggTaskNum"); i != nil {
		data, _ = i.(map[int32]int32)
	}
	if data == nil {
		data = make(map[int32]int32)
	}
	data[id] += 1
	daily.Set("eggTaskNum", data)
}

// refresh 刷新 todo 周限制
func (this *egg) refresh(p *player.Player, egg *model.EggPool) error {
	values := map[int32]int32{}
	var ifEgg bool
	dailyHandle := itypes.Daily.Handle(p.Updater)
	dailyData := dailyHandle.All()

	CatcherPool := dailyData.CatcherPool
	if CatcherPool == nil {
		CatcherPool = make(map[int32]int32)
	}
	var catcherPoolChanged bool

	for _, v := range config.GetEggPoolConfig(egg.IID) {
		if v.NumPerWeek > 0 {
			if n := CatcherPool[v.Id]; n >= v.NumPerWeek {
				continue
			} else {
				catcherPoolChanged = true
				CatcherPool[v.Id] = n + 1
			}
		}
		rdm := random.Random{}
		for _, i := range v.ProGroup {
			rdm.Add(i.Num, i.Pro)
		}
		if n := rdm.Sort().Roll(); n > 0 {
			values[v.GroupId] += n
			if v.IfEgg > 0 {
				ifEgg = true
			}
		}
	}

	if catcherPoolChanged {
		dailyHandle.Set("catcherPool", CatcherPool)
	}
	//保底
	if !ifEgg {
		catcherPoolConfig := config.Data.CatcherPoolConfig[egg.IID]
		if catcherPoolConfig == nil {
			return errors.ErrConfigEmpty
		}
		arr := slice.SplitAndUnrepeated(catcherPoolConfig.GuaranteedEggGroup, ",")
		if len(arr) > 0 {
			if k := slice.Roll(arr); k > 0 {
				values[k] = 1
			}
		}

	}
	egg.Values = values
	return db.Select("values").Update(egg, egg.OID).Error

}

/**
 * @name getEggPool
 * @param int id 蛋池ID  //实际值为INT
 * 拉蛋池数据
 */
func (this *egg) GetEggPool(c *context.Context) any {
	id := c.GetInt32("id")
	if id == 0 {
		return errors.ErrArgEmpty
	}
	catcherPoolConfig := config.Data.CatcherPoolConfig[id]
	if catcherPoolConfig == nil {
		return errors.ErrConfigEmpty
	}
	//if catcherPoolConfig.Exist == 0 {
	//	return c.Error("catcherPoolConfig Not Exist")
	//}

	eggPool := model.NewEggPool(c.Player.Updater, id)
	if err := db.Find(eggPool, eggPool.OID).Error; err != nil {
		return err
	}
	var num int32
	//判定是不是全是石头
	refreshEggPool := config.Data.Base["refreshEggPool"]
	if refreshEggPool == nil {
		return c.Error("config Base refreshEggPool is nil")
	}
	arr := slice.SplitInt32(refreshEggPool.StrVal, ",")
	for k, v := range eggPool.Values {
		if v > 0 && !slice.Has(arr, k) {
			num++
		}
	}
	if num == 0 {
		if err := this.refresh(c.Player, eggPool); err != nil {
			return err
		}
	}
	return eggPool.Values
}

/**
 * @name refreshEggPool
 * @param int id 蛋池ID
 * 刷新蛋池数据
 */
func (this *egg) RefreshEggPool(c *context.Context) any {
	id := c.GetInt32("id")
	if id == 0 {
		return errors.ErrArgEmpty
	}
	catcherPoolConfig := config.Data.CatcherPoolConfig[id]
	if catcherPoolConfig == nil {
		return errors.ErrConfigEmpty
	}
	//if catcherPoolConfig.Exist == 0 {
	//	return c.Error("catcherPoolConfig Not Exist")
	//}
	if catcherPoolConfig.RefreshCost > 0 && catcherPoolConfig.RefreshCostNum > 0 {
		v := c.Player.Val(catcherPoolConfig.RefreshCost)
		if v < int64(catcherPoolConfig.RefreshCostNum) {
			return errors.ErrItemNotEnough
		}
		c.Player.Sub(catcherPoolConfig.RefreshCost, catcherPoolConfig.RefreshCostNum)
	}

	eggPool := model.NewEggPool(c.Player.Updater, id)
	if err := this.refresh(c.Player, eggPool); err != nil {
		return err
	}
	return eggPool.Values

}

/**
 * @name catchEgg
 * @param string id 蛋池ID
 * @param int catchId 爪子ID
 * @param json rewardData  物品ID:数量
 * 抓蛋奖励
 */
func (this *egg) CatchEgg(c *context.Context) any {
	args := struct {
		Id         int32           `json:"id"`
		CatchId    int32           `json:"catchId"`
		RewardData map[int32]int32 `json:"rewardData"`
	}{
		RewardData: map[int32]int32{},
	}
	if err := c.Bind(&args); err != nil {
		return err
	}
	catcherPoolConfig := config.Data.CatcherPoolConfig[args.Id]
	if catcherPoolConfig == nil {
		return errors.ErrConfigEmpty
	}
	catchConfig := config.Data.CatcherConfig[args.CatchId]
	if catchConfig == nil {
		return errors.ErrConfigEmpty
	}
	if !slice.Has(catcherPoolConfig.CatcherList, args.CatchId) {
		return c.Error("catchId error")
	}

	eggPool := model.NewEggPool(c.Player.Updater, args.Id)
	if err := db.Find(eggPool, eggPool.OID).Error; err != nil {
		return err
	}
	if len(eggPool.Values) == 0 {
		return errors.ErrDataNotExists
	}
	values := utils.CloneMap(eggPool.Values)
	c.Player.SubItems(catchConfig.ItemCost)
	reward := make(map[int32]int32)
	var num int32
	for k, v := range args.RewardData {
		if v <= 0 {
			return c.Errorf(0, "RewardData value is empty:%d", k)
		}
		if m := values[k]; v > m {
			return c.Errorf(0, "not enough,id:%d ,%d/%d", k, m, v)
		}
		values[k] -= v
		itypes.ItemsBong.Parse(c.Player.Updater, reward, k, v)
		num++
		if num >= catchConfig.MaxCatch {
			break
		}
	}
	task := cache.GetTask(c.Player.Updater)
	//当前任务数
	var tn int32
	now := c.Unix()
	task.Range(func(id string, v *model.Task) bool {
		if tc := config.Data.Task[v.IID]; tc != nil && tc.Tag == config.Data.TaskTag.EggTask && v.IsValid(now) {
			tn++
		}
		return true
	})
	//今日刷到任务蛋数量
	dailyDoc := itypes.Daily.Handle(c.Player.Updater)
	dailyData := dailyDoc.All()
	var dailyNum int32
	//eggTaskNum := utils.CloneMap(dailyData.EggTaskNum)
	for _, v := range dailyData.EggTaskNum {
		dailyNum += v
	}

	var changeNum int32
	var acceptNum int32
	for k, v := range reward {
		if !strings.HasPrefix(strconv.Itoa(int(k)), "90") {
			c.Player.Add(k, v)
		} else {
			//蛋任务
			if dailyNum+acceptNum >= config.Data.BaseN.EggTaskMaxNumDaily || tn+acceptNum >= config.Data.BaseN.EggTaskMaxNum {
				changeNum++
				ec := config.Data.Base["eggTaskMaxNumExchange"]
				if eggTaskMaxNumExchangeArr := slice.SplitInt32(ec.StrVal); len(eggTaskMaxNumExchangeArr) >= 2 {
					c.Player.Add(eggTaskMaxNumExchangeArr[0], eggTaskMaxNumExchangeArr[1])
				}
			} else if err := task.Accept(k); err == nil {
				acceptNum++
				//eggTaskNum[k] += 1
			} else {
				return err
			}
		}
	}
	//if acceptNum > 0 {
	//	dailyDoc.Set("eggTaskNum", eggTaskNum)
	//}

	c.Player.Updater.On(updater.EventTypeSuccess, func(u *updater.Updater) (next bool) {
		if err := db.Model(eggPool).Where(eggPool.OID).Set("values", values).Error; err != nil {
			logger.Alert("update eggPool fail:%+v", eggPool)
		}
		return false
	})

	ret := map[string]any{}

	ret["values"] = values
	ret["changeNum"] = changeNum

	c.Player.Emit(config.Data.Events.CatcherPoolCatch, 1)
	return ret
}

/**
 * @name shakeEggPool
 * @param int id 蛋池ID
 * 抖下蛋池
 */
func (this *egg) ShakeEggPool(c *context.Context) any {
	id := c.GetInt32("id")
	if id == 0 {
		return errors.ErrArgEmpty
	}
	catcherPoolConfig := config.Data.CatcherPoolConfig[id]
	if catcherPoolConfig == nil {
		return errors.ErrConfigEmpty
	}
	c.Player.Sub(catcherPoolConfig.ShakeCost, catcherPoolConfig.ShakeCostNum)
	return nil
}

/**
 * @name refreshStonePool
 * @param int id 蛋池ID
 * 刷新只剩下石头的蛋池
 */
func (this *egg) RefreshStonePool(c *context.Context) any {
	return this.GetEggPool(c)
}

/**
 * @name DeleteEggTask
 * @param int id 任务ID
 * 放弃蛋蛋任务
 */
func (this *egg) DeleteEggTask(c *context.Context) any {
	id := c.GetInt32("id")
	taskConfig := config.Data.Task[id]
	if taskConfig == nil {
		return errors.ErrConfigEmpty
	}
	if taskConfig.Tag != config.Data.TaskTag.EggTask {
		return errors.Errorf(0, "eggTask tag is not eggTask")
	}
	taskColl := cache.GetTask(c.Player.Updater)
	taskData := taskColl.Get(taskConfig.Id)
	if taskData == nil {
		return false
	}
	if !taskData.IsValid(c.Unix()) {
		return false //已完成或者过期无需放弃
	}
	dailyDoc := itypes.Daily.Handle(c.Player.Updater)
	dailyData := dailyDoc.All()
	if dailyData.EggTaskDel >= config.Data.BaseN.EggTaskDeleteFree {
		ec := config.Data.Base["dailyTaskDeleteCost"]
		if arr := slice.SplitInt32(ec.StrVal); len(arr) >= 2 {
			c.Player.Sub(arr[0], arr[1])
		}
	}
	dailyDoc.Add("EggTaskDel", 1)
	taskColl.Del(taskData.OID)
	return true
}
